package com.chuangke.framework.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.chuangke.common.exception.ChuangkeException;
import com.chuangke.framework.model.LevelModel;

import cn.hutool.core.util.StrUtil;

public class TreeUtils {

	/**
	 * 将父子关系的tree转出list
	 * 
	 * @param <T>
	 * @param treeList
	 * @return
	 */
	public static <T extends LevelModel<T>> List<T> treeToList(List<T> treeList) {
		List<T> list = new ArrayList<>();

		deepIterate(treeList, list);

		return list;
	}

	private static <T extends LevelModel<T>> void deepIterate(List<T> iteratorList, List<T> distList) {
		if (CollectionUtils.isEmpty(iteratorList)) {
			return;
		}
		for (T svmc : iteratorList) {
			distList.add(svmc);
			deepIterate(svmc.getChildren(), distList);
		}
	}

	/**
	 * 将list转换成tree
	 * 
	 * @param <T>
	 * @param list
	 * @return
	 */
	public static <T extends LevelModel<T>> List<T> buildTree(List<T> list) {
		list.sort((dept1, dept2) -> {
			if (dept1.getId().length() != dept2.getId().length()) {
				return dept1.getId().length() - dept2.getId().length();
			}
			return dept1.getId().compareTo(dept2.getId());
		});

		List<T> tree = new ArrayList<>();
		for (T bean : list) {
			if (bean.getParentId() == null || bean.getParentId().trim().isEmpty() || "0".equals(bean.getParentId())) {
				tree.add(bean);
			}
		}
		findChildren(tree, list);
		return tree;
	}

	private static <T extends LevelModel<T>> void findChildren(List<T> tree, List<T> lists) {
		for (T treeBean : tree) {
			List<T> children = new ArrayList<>();
			for (T bean : lists) {
				if (treeBean.getId() != null && treeBean.getId().equals(bean.getParentId())) {
					bean.setParentName(treeBean.getName());
					children.add(bean);
				}
			}
			treeBean.setChildren(children);
			findChildren(children, lists);
		}
	}

	/**
	 * 对数据进行分级，更新数据的level,is_last_level,data_domain
	 * 
	 * @param parentDataDomain 如果是一级传空""
	 * @param parenLevel       如果是一级传0
	 * @param oldList
	 */
	public static <T extends LevelModel<T>> void level(String parentDataDomain, int parenLevel, List<T> oldList,
			List<T> newList) {
		int firstCode = 1001;
		for (T treeBean : oldList) {
			treeBean.setDataDomain(parentDataDomain + firstCode);
			treeBean.setLevel(parenLevel + 1);
			treeBean.setIsLastLevel(CollectionUtils.isEmpty(treeBean.getChildren()) ? "1" : "0");
			newList.add(treeBean);
			firstCode++;
			level(treeBean.getDataDomain(), treeBean.getLevel(), treeBean.getChildren(), newList);
		}
	}

	/**
	 * 查找树形的末级
	 * 
	 * @param <T>
	 * @param treeList
	 * @param lastLevelList
	 */
	public static <T extends LevelModel<T>> void findLastLevel(List<T> treeList, List<T> lastLevelList) {
		for (T treeBean : treeList) {
			if (CollectionUtils.isEmpty(treeBean.getChildren())) {
				lastLevelList.add(treeBean);
			} else {
				findLastLevel(treeBean.getChildren(), lastLevelList);
			}
		}
	}

	/**
	 * 根据级数查找指定级数的数据
	 * 
	 * @param <T>
	 * @param list
	 * @param level
	 * @return
	 */
	public static <T extends LevelModel<T>> List<T> findByLevel(List<T> list, int level) {
		List<T> result = new ArrayList<>();
		for (T sysDept : list) {
			if (sysDept.getLevel() == level) {
				result.add(sysDept);
			}
		}
		return result;
	}

	/**
	 * 查找指定血缘关系的上下级
	 * 
	 * @param <T>
	 * @param noChildMap
	 * @param withChildrenList
	 * @param idList
	 * @return
	 */
	public static <T extends LevelModel<T>> List<T> findKinshipTree(Map<String, T> noChildMap, List<T> withChildrenList,
			Collection<String> idList) {
		Map<String, T> withChildmap = withChildrenList.stream().collect(Collectors.toMap(T::getId, a -> a));

		Map<String, T> kinshipMap = new HashMap<>();// 里面包含了本身及直接的上下级
		for (String deptId : idList) {
			T own = withChildmap.get(deptId);
			if (own == null) {
				continue;
			}
			// 将子集放进去
			fillChildTreeToList(noChildMap, own, kinshipMap);

			// 将父集放进去
			fillParentToList(noChildMap, noChildMap.get(deptId), kinshipMap);
		}

		List<T> kinshipList = new ArrayList<>(kinshipMap.values());
		kinshipList.forEach(dept -> dept.setChildren(null));
		return TreeUtils.buildTree(kinshipList);
	}

	private static <T extends LevelModel<T>> void fillChildTreeToList(Map<String, T> deptMap, T dept,
			Map<String, T> kinshipMap) {
		if (dept == null) {
			return;
		}
		// 因为dept是分级的，包含了子集，所以不直接加入到deptList
		kinshipMap.put(dept.getId(), deptMap.get(dept.getId()));

		if (CollectionUtils.isEmpty(dept.getChildren())) {
			return;
		}

		for (T sd : dept.getChildren()) {
			fillChildTreeToList(deptMap, sd, kinshipMap);
		}
	}

	private static <T extends LevelModel<T>> void fillParentToList(Map<String, T> deptMap, T dept,
			Map<String, T> kinshipMap) {
		if (dept == null) {
			return;
		}

		kinshipMap.put(dept.getId(), dept);

		String parentId = dept.getParentId();
		if (StrUtil.isBlank(dept.getParentId()) || dept.getParentId().trim().isEmpty()
				|| "0".equals(dept.getParentId())) {
			return;
		}

		T parentDept = deptMap.get(parentId);

		fillParentToList(deptMap, parentDept, kinshipMap);
	}

	/**
	 * 获取父级
	 * 
	 * @param <T>
	 * @param deptId
	 * @param noChildMap
	 * @return
	 */
	public static <T extends LevelModel<T>> T getParent(String deptId, Map<String, T> noChildMap) {
		T dept = noChildMap.get(deptId);
		if (dept == null) {
			return null;
		}

		if (dept.getLevel() == 1) {
			return dept;
		} else {
			return getParent(dept.getParentId(), noChildMap);
		}
	}

	/**
	 * 获取所有子节点
	 * @param <T>
	 * @param resultList
	 * @param dataList
	 */
	public static <T extends LevelModel<T>> void foreachChildren(List<T> resultList, List<T> dataList) {
		if (CollectionUtils.isEmpty(dataList)) {
			return;
		}

		for (T dept : dataList) {
			resultList.add(dept);
			foreachChildren(resultList, dept.getChildren());
		}
	}
	
	/**
	 * 根据分组字段对数据进行构建上级数据
	 * @param groupColums
	 * @param dataMap
	 */
	public static List<Map<String, Object>> buildParentDataByGroup(List<String> groupColums, List<Map<String, Object>> dataMap) {
		if(CollectionUtils.isEmpty(groupColums)) {
			throw new ChuangkeException("未配置分级分组字段") ;
		}
		
		int id = 1 ;
		Map<String,Map<String,Object>> parentDataMap = new HashMap<>() ;
		for(Map<String, Object> data : dataMap) {
			String parentKey = getParentKey(groupColums,data) ;
			if(!parentDataMap.containsKey(parentKey)) {
				Map<String,Object> parentData = createParentData(groupColums,data) ;
				parentData.put("levelId", (id++) +"") ;
				parentData.put("levelParentId", null) ;
				parentDataMap.put(parentKey, parentData) ;
				
				data.put("levelParentId", parentData.get("levelId")) ;
			}else {
				data.put("levelParentId", parentDataMap.get(parentKey).get("levelId")) ;
			}
			data.put("levelId", (id++) + "") ;
		}
		
		dataMap.addAll(parentDataMap.values());
		
//		List<Map<String, Object>> newDataMap  = new ArrayList<>() ;
//		parentDataMap.values().forEach(data -> {
//			newDataMap.add(data) ;
//			newDataMap.addAll(dataMap.stream().filter(d -> data.get("id").equals(d.get("parentId"))).toList()) ;
//		});
		
		return dataMap ;
	}
	
	private static Map<String,Object> createParentData(List<String> groupColumns,Map<String, Object> data) {
		Map<String,Object> parentData = new HashMap<>() ;
		for(String groupColum : groupColumns) {
			Object  value = ObjectUtils.isEmpty(data.get(groupColum)) ? "未定义值":data.get(groupColum);
			parentData.put(groupColum, value);
		}
		return parentData ;
	}
	
	private static String getParentKey(List<String> groupColumns,Map<String, Object> data) {
		StringBuilder key = new StringBuilder() ;
		for(int i=0; i<groupColumns.size(); i++) {
			String value = data.getOrDefault(groupColumns.get(i), "").toString() ;
			key.append(value) ;
			if(i<(groupColumns.size()-1)) {
				key.append("-") ;
			}
		}
		return key.toString() ;
	}
}
